﻿using System;
using System.Text;
using System.Data;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using Estimate.Common.Entity;
using Estimate.Common.DBFieldTypes;
using Estimate.Common.Repository;
using Estimate.Common.Estimate;
using Estimate.Common.Estimate.EstimateValue;
using Newtonsoft.Json;

namespace Estimate.Reports
{
    /// <summary>
    /// 全信息报表类
    /// 根据给定的semi生成相应的处理结果
    /// </summary>
    public class FullInfoReport : BaseReport
    {
        #region 变量与对象
        /// <summary>
        /// 需要计算排名的城镇列表
        /// </summary> 
        public Dictionary<string, string> CityCodes;

        /// <summary>
        /// 需要计算排名的预报员的排班表
        /// </summary> 
        public List<ScheduleEntity> IndividualSchedules;

        /// <summary>
        /// 格式化后的排班表记录
        /// </summary>
        Dictionary<DateTime, Dictionary<ForeClockType, Dictionary<ForeSendpointType, List<ScheduleEntity>>>> Schedules;

        /// <summary>
        /// 获取semi的数据检索对象
        /// </summary>
        public ForeRepository DataProvider;

        private ExecutionStatus exeStatus = null;//程序执行状态
        /// <summary>
        /// 程序执行状态
        /// </summary>
        public ExecutionStatus ExeStatus
        {
            set { exeStatus = value; }
        }

        /// <summary>
        /// 计算综合分的方式
        /// </summary>
        //public CompositeScoreKind CompositeKind = CompositeScoreKind.Individual;

        /// <summary>
        /// 计算的综合分，是否是短期的综合分
        /// 如果是短期的，则会使用 FD00_24 及 FD24__48 下的分数计算
        /// 如果是中期的，则会使用 FD00_96 及 FD96_120 来计算
        /// </summary>
        public bool IsShortCompositeScore = true;
        public void SetCompositeScoreIsShort(bool value)
        {
            IsShortCompositeScore = value;
        }

        /// <summary>
        /// semi为空的记录
        /// </summary>
        public List<ForeEntity> EmptySemis = new List<ForeEntity>();

        #region 存储降水、温度、预报偏差得分、样本数的字典
        /// <summary>
        /// 分级检验降水
        /// 外层字典key:cityCode或forecast,第二层字典key:PrecipitationLevel,内层字典key:ForeSpanType
        /// </summary>
        public Dictionary<string, Dictionary<PrecipitationLevel, Dictionary<ForeSpanType, WaterScore>>> PrecipitationWaterScore;
        /// <summary>
        /// 降水程度，分一般性降水和暴雨以上
        /// 外层字典key:cityCode或forecast,第二层字典key:WaterfallLevel,内层字典key:ForeSpanType
        /// </summary>
        public Dictionary<string,Dictionary<WaterfallLevel, Dictionary<ForeSpanType, WaterScore>>> WaterfallLevelWaterScore;
        /// <summary>
        /// 累加降水
        /// 外层字典key:cityCode或forecast,第二层字典key:SumPrecipitationLevel,内层字典key:ForeSpanType
        /// </summary>
        public Dictionary<string,Dictionary<SumPrecipitationLevel, Dictionary<ForeSpanType, WaterScore>>> SumPrecipitationWaterScore;
        /// <summary>
        /// 晴雨检验
        /// 外层字典key:cityCode或forecast,内层字典key:ForeSpanType
        /// </summary>
        public Dictionary<string,Dictionary<ForeSpanType, WaterScore>> WaterfallAmountWaterScore;
        /// <summary>
        /// 最高气温
        /// 外层字典key:cityCode或forecast,内层字典key:ForeSpanType
        /// </summary>
        public Dictionary<string,Dictionary<ForeSpanType, TempScore>> MaxTempScore;
        /// <summary>
        /// 最低气温
        /// 外层字典key:cityCode或forecast,内层字典key:ForeSpanType
        /// </summary>
        public Dictionary<string,Dictionary<ForeSpanType, TempScore>> MinTempScore;
        /// <summary>
        /// 偏差结果数组
        /// 值：DeviationKind,X,Y,LackCount,EmptyCount
        /// </summary>
        public List<DeviationResult> DeviationResults;
        /// <summary>
        /// 存储预报员晴雨检验样本记录数
        /// 外层字典key:cityCode或forecast,最内层字典key:年月
        /// </summary>
        public Dictionary<string, Dictionary<ForeSpanType, Dictionary<DateTime, int>>> RecordCount;

        public Dictionary<string, int> ScheduleCount;

        #endregion

        #region 每种分数是否需要计算的控制
        /// <summary>
        /// 是否计算天气分数,天气分为分级检验降水、降水程度、累加降水、晴雨检验
        /// 只有CulculateWeatherScore=true时，才能对分级检验降水、降水程度、累加降水、晴雨检验计算进行控制
        /// 默认值为false
        /// </summary>
        public bool CulculateWeatherScore = false;

        /// <summary>
        /// 是否计算分级检验降水分数
        /// 默认值为false
        /// </summary>
        public bool CulculatePrecipitationWaterScore = false;

        /// <summary>
        /// 是否计算降水程度分数
        /// 默认值为false
        /// </summary>
        public bool CulculateWaterfallLevelWaterScore = false;

        /// <summary>
        /// 用于临时控制是否继续计算某个24小时span的降水程度分数
        /// </summary>
        private bool TemCulculateWaterfallLevelWaterScore = false;

        /// <summary>
        /// 是否以12小时为检验单元计算降水程度分数
        /// </summary>
        public bool CulculateWaterfallLevelSplitFD24ToFD12 = false;

        /// <summary>
        /// 是否计算累加降水分数
        /// 默认值为false
        /// </summary>
        public bool CulculateSumPrecipitationWaterScore = false;

        /// <summary>
        /// 是否计算晴雨检验分数
        /// 默认值为false
        /// </summary>
        public bool CulculateWaterfallAmountWaterScore = false;

        /// <summary>
        /// 用于临时控制是否继续计算某个24小时span的晴雨检验
        /// </summary>
        private bool TemCulculateWaterfallAmountWaterScore = false;

        /// <summary>
        /// 是否以12小时为检验单元计算晴雨检验
        /// </summary>
        public bool CulculateWaterfallAmountSplitFD24ToFD12 = true;

        /// <summary>
        /// 是否计算最高气温分数
        /// 默认值为false
        /// </summary>
        public bool CulculateMaxTempScore = false;

        /// <summary>
        /// 是否计算最低气温分数
        /// 默认值为false
        /// </summary>
        public bool CulculateMinTempScore = false;

        /// <summary>
        /// 是否计算预报偏差结果
        /// 默认值为false
        /// </summary>
        public bool CulculateDeviationResult = false;

        /// <summary>
        /// 是否计算全部得分
        /// </summary>
        public bool CulculateAllResult
        {
            set
            {
                CulculateWeatherScore = value;
                CulculatePrecipitationWaterScore = value;
                CulculateWaterfallLevelWaterScore = value;
                CulculateSumPrecipitationWaterScore = value;
                CulculateWaterfallAmountWaterScore = value;
                CulculateMaxTempScore = value;
                CulculateMinTempScore = value;
                CulculateDeviationResult = value;
            }
        }

        #endregion

        #region 获取Semi的检索条件值
        public DateTime _beginDate;
        public DateTime _endDate;
        public ForeSemiType _realtype;
        public ForeSpanType[] _waterSpans;
        public ForeSpanType[] _tempSpans;
        public ForeSendpointType[] _sendpoints;
        #endregion
       
        #endregion

        #region 构造函数
        /// <summary>
        ///全信息处理报表类,构造函数
        /// </summary>
        /// <param name="provider">获取基础数据的对象</param>
        /// <param name="cityCodes">需要计算排名的城镇</param>
        public FullInfoReport(string connectionString, ForeRepository provider, Dictionary<string, string> cityCodes)
            : base(connectionString)
        {
            DataProvider = provider;
            CityCodes = cityCodes;
        }

        /// <summary>
        /// 全信息处理报表类,构造函数
        /// </summary>
        /// <param name="cityCodes">需要计算排名的预报员排班表</param>
        public FullInfoReport(string connectionString, ForeRepository provider, List<ScheduleEntity> individualSchedules)
             : base(connectionString)
        {
            DataProvider = provider;
            IndividualSchedules = individualSchedules;
        }

        /// <summary>
        /// 全信息处理报表类,构造函数
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="provider">semi检索方法对象</param>
         public FullInfoReport(string connectionString,ForeRepository provider)
             : base(connectionString)
        {
            DataProvider = provider;
        }

         //public FullInfoReport(string connectionString, ForeRepository provider)
         //    : base(connectionString)
         //{
         //    DataProvider = provider;
         //    //CompositeKind = compositeKind;
         //}

         public FullInfoReport(string connectionString)
             : base(connectionString)
         {
            
         }
        #endregion

        #region 初始化存储得分的字典
        /// <summary>
        /// 初始化存储得分的字典
        /// </summary>
        /// <param name="waterSpans">降水预报时效</param>
        /// <param name="tempSpans">气温预报时效</param>
        private void InitScore(ForeSpanType[] waterSpans, ForeSpanType[] tempSpans)
        {
            Clear();

            if (CityCodes != null)
            {
                foreach (string city in CityCodes.Values)
                    InitScore(city, waterSpans, tempSpans);
            }

            else if (IndividualSchedules != null)
            {
                foreach (ScheduleEntity schedule in IndividualSchedules)
                {
                    //格式化IndividualSchedules，加速查询比较
                    if (Schedules == null)
                        Schedules = new Dictionary<DateTime, Dictionary<ForeClockType, Dictionary<ForeSendpointType, List<ScheduleEntity>>>>();
                    if (!Schedules.ContainsKey(schedule.RealDate))
                        Schedules.Add(schedule.RealDate, new Dictionary<ForeClockType, Dictionary<ForeSendpointType, List<ScheduleEntity>>>());
                    if (!Schedules[schedule.RealDate].ContainsKey(schedule.Clock))
                        Schedules[schedule.RealDate].Add(schedule.Clock, new Dictionary<ForeSendpointType, List<ScheduleEntity>>());
                    if (!Schedules[schedule.RealDate][schedule.Clock].ContainsKey(schedule.Sendpoint))
                        Schedules[schedule.RealDate][schedule.Clock].Add(schedule.Sendpoint, new List<ScheduleEntity>());
                    Schedules[schedule.RealDate][schedule.Clock][schedule.Sendpoint].Add(schedule);

                    //key格式为"站点号_预报员编号;站点名称"
                    string key = GlobalFunction.AssemblyForecastNum(schedule);
                    InitScore(key, waterSpans, tempSpans);

                    if (ScheduleCount == null)
                        ScheduleCount = new Dictionary<string, int>();
                    if (!ScheduleCount.ContainsKey(key))
                        ScheduleCount.Add(key, 1);
                    else
                        ScheduleCount[key] += 1;
                }
            }
            else
                InitScore("", waterSpans, tempSpans);

            //初始化偏差分数字典
            if (CulculateDeviationResult)
                DeviationResults = new List<DeviationResult>();
        }

        /// <summary>
        /// 初始化存储得分的字典
        /// </summary>
        /// <param name="waterSpans">降水预报时效</param>
        /// <param name="tempSpans">气温预报时效</param>
        private void InitScore(string key, ForeSpanType[] waterSpans, ForeSpanType[] tempSpans)
        {
            #region 初始化分级检验分数字典
            if (CulculatePrecipitationWaterScore )
            {
                if (PrecipitationWaterScore == null)
                    PrecipitationWaterScore = new Dictionary<string, Dictionary<PrecipitationLevel, Dictionary<ForeSpanType, WaterScore>>>();
                if (!PrecipitationWaterScore.ContainsKey(key))
                {
                    PrecipitationWaterScore.Add(key, new Dictionary<PrecipitationLevel, Dictionary<ForeSpanType, WaterScore>>());
                    PrecipitationWaterScore[key] = new Dictionary<PrecipitationLevel, Dictionary<ForeSpanType, WaterScore>>(10);
                    foreach (PrecipitationLevel level in Enum.GetValues(typeof(PrecipitationLevel)))
                    {
                        if ((int)level < 1 || (int)level == 7) continue;//除故障和无降水的情况，并排除雨夹雪情况

                        foreach (ForeSpanType span in waterSpans)
                        {
                            if (!PrecipitationWaterScore[key].ContainsKey(level))
                                PrecipitationWaterScore[key].Add(level, new Dictionary<ForeSpanType, WaterScore>(waterSpans.Length));

                            PrecipitationWaterScore[key][level].Add(span, new WaterScore());
                        }
                    }
                }
            }
            #endregion

            #region 初始化累加降水分数字典
            if (CulculateSumPrecipitationWaterScore)
            {
                if (SumPrecipitationWaterScore == null)
                    SumPrecipitationWaterScore = new Dictionary<string, Dictionary<SumPrecipitationLevel, Dictionary<ForeSpanType, WaterScore>>>();
                if (!SumPrecipitationWaterScore.ContainsKey(key))
                {
                    SumPrecipitationWaterScore.Add(key, new Dictionary<SumPrecipitationLevel, Dictionary<ForeSpanType, WaterScore>>());
                    SumPrecipitationWaterScore[key] = new Dictionary<SumPrecipitationLevel, Dictionary<ForeSpanType, WaterScore>>(4);
                    foreach (SumPrecipitationLevel level in Enum.GetValues(typeof(SumPrecipitationLevel)))
                    {
                        if ((int)level < 1) continue;//除故障和无降水的情况，并排除雨夹雪情况

                        foreach (ForeSpanType span in waterSpans)
                        {
                            if (!SumPrecipitationWaterScore[key].ContainsKey(level))
                                SumPrecipitationWaterScore[key].Add(level, new Dictionary<ForeSpanType, WaterScore>(waterSpans.Length));

                            SumPrecipitationWaterScore[key][level].Add(span, new WaterScore());
                        }
                    }
                }
            }
            #endregion

            #region 初始化一般降水及暴雨以上分数字典
            if (CulculateWaterfallLevelWaterScore )
            {
                if (WaterfallLevelWaterScore == null)
                    WaterfallLevelWaterScore = new Dictionary<string, Dictionary<WaterfallLevel, Dictionary<ForeSpanType, WaterScore>>>();
                if (!WaterfallLevelWaterScore.ContainsKey(key))
                {
                    WaterfallLevelWaterScore.Add(key, new Dictionary<WaterfallLevel, Dictionary<ForeSpanType, WaterScore>>());
                    WaterfallLevelWaterScore[key] = new Dictionary<WaterfallLevel, Dictionary<ForeSpanType, WaterScore>>(2);
                    foreach (WaterfallLevel level in Enum.GetValues(typeof(WaterfallLevel)))
                    {
                        //WaterfallLevel level = (WaterfallLevel)Enum.Parse(typeof(WaterfallLevel), strLevel);
                        if ((int)level < 1) continue;//除故障和无降水的情况，并排除雨夹雪情况

                        foreach (ForeSpanType span in waterSpans)
                        {
                            if (!WaterfallLevelWaterScore[key].ContainsKey(level))
                                WaterfallLevelWaterScore[key].Add(level, new Dictionary<ForeSpanType, WaterScore>(waterSpans.Length));

                            WaterfallLevelWaterScore[key][level].Add(span, new WaterScore());
                        }
                    }
                }
            }
            #endregion

            #region 初始化晴雨分数字典
            if (CulculateWaterfallAmountWaterScore)
            {
                if (WaterfallAmountWaterScore == null)
                    WaterfallAmountWaterScore = new Dictionary<string, Dictionary<ForeSpanType, WaterScore>>();
                if (!WaterfallAmountWaterScore.ContainsKey(key))
                {
                    WaterfallAmountWaterScore.Add(key, new Dictionary<ForeSpanType, WaterScore>());
                    WaterfallAmountWaterScore[key] = new Dictionary<ForeSpanType, WaterScore>();
                    foreach (ForeSpanType span in waterSpans)
                        WaterfallAmountWaterScore[key].Add(span, new WaterScore());
                }
            }
            #endregion

            #region 初始化最高温分数字典
            if (CulculateMaxTempScore)
            {
                if (MaxTempScore == null)
                    MaxTempScore = new Dictionary<string, Dictionary<ForeSpanType, TempScore>>();
                if (!MaxTempScore.ContainsKey(key))
                {
                    MaxTempScore.Add(key, new Dictionary<ForeSpanType, TempScore>());
                    MaxTempScore[key] = new Dictionary<ForeSpanType, TempScore>();
                    foreach (ForeSpanType span in tempSpans)
                        MaxTempScore[key].Add(span, new TempScore());
                }
            }
            #endregion

            #region 初始化最低温分数字典
            if (CulculateMinTempScore )
            {
                if (MinTempScore == null)
                    MinTempScore = new Dictionary<string, Dictionary<ForeSpanType, TempScore>>();
                if (!MinTempScore.ContainsKey(key))
                {
                    MinTempScore.Add(key, new Dictionary<ForeSpanType, TempScore>());
                    MinTempScore[key] = new Dictionary<ForeSpanType, TempScore>();
                    foreach (ForeSpanType span in tempSpans)
                        MinTempScore[key].Add(span, new TempScore());
                }
            }
            #endregion

            #region 初始化样本记录字典
            if (RecordCount == null)
                RecordCount = new Dictionary<string, Dictionary<ForeSpanType, Dictionary<DateTime, int>>>();
            if (!RecordCount.ContainsKey(key))
            {
                RecordCount[key] = new Dictionary<ForeSpanType, Dictionary<DateTime, int>>();
                foreach (ForeSpanType span in waterSpans)
                    RecordCount[key].Add(span, new Dictionary<DateTime, int>());
            }
           #endregion
        }

        /// <summary>
        /// 清除数据
        /// </summary>
        public void Clear()
        {
            if (PrecipitationWaterScore!=null) PrecipitationWaterScore.Clear();
            if (WaterfallLevelWaterScore != null) WaterfallLevelWaterScore.Clear();
            if (SumPrecipitationWaterScore != null) SumPrecipitationWaterScore.Clear();
            if (WaterfallAmountWaterScore != null) WaterfallAmountWaterScore.Clear();
            if (MaxTempScore != null) MaxTempScore.Clear();
            if (MinTempScore != null) MinTempScore.Clear();
            if (DeviationResults != null) DeviationResults.Clear();
            if (RecordCount != null) RecordCount.Clear();
            if (Schedules != null) Schedules.Clear();
        }
        #endregion

        #region 数据准备并计算
        /// <summary>
        /// 数据准备并计算
        /// </summary>
        /// <param name="beginDate">开始日期</param>
        /// <param name="endDate">结束日期</param>
        /// <param name="realtype">实况类型</param>
        /// <param name="sendpoints">发报时刻</param>
        public virtual void PrepareData(DateTime beginDate, DateTime endDate, ForeSemiType realtype, ForeSendpointType[] sendpoints)
        {

            ForeSpanType[] waterSpans = new ForeSpanType[]{
                ForeSpanType.FD00_12,
                ForeSpanType.FD12_24,
                ForeSpanType.FD00_24,
                ForeSpanType.FD24_48,
                ForeSpanType.FD48_72,
                ForeSpanType.FD72_96,
                ForeSpanType.FD96_120,
                ForeSpanType.FD120_144,
                ForeSpanType.FD144_168
            };

            ForeSpanType[] tempSpans = new ForeSpanType[] { ForeSpanType.FD00_24,
                                                                   ForeSpanType.FD24_48,
                                                                   ForeSpanType.FD48_72, 
                                                                   ForeSpanType.FD72_96,
                                                                   ForeSpanType.FD96_120,
                                                                   ForeSpanType.FD120_144,
                                                                   ForeSpanType.FD144_168
                                                                };
            PrepareData(beginDate, endDate, realtype, waterSpans, tempSpans, sendpoints);
        }

       /// <summary>
       /// 数据准备并计算
       /// </summary>
       /// <param name="beginDate">开始时间</param>
       /// <param name="endDate">结束时间</param>
       /// <param name="realtype">实况类型</param>
       /// <param name="waterSpans">天气时效</param>
       /// <param name="tempSpans">温度时效</param>
       /// <param name="sendpoints">发报时间</param>
        public void PrepareData(DateTime beginDate, DateTime endDate, ForeSemiType realtype, ForeSpanType[] waterSpans, ForeSpanType[] tempSpans, ForeSendpointType[] sendpoints)
        {
            _beginDate = beginDate;
            _endDate = endDate;
            _realtype = realtype;
            _waterSpans = waterSpans;
            _tempSpans = tempSpans;
            _sendpoints = sendpoints;

            if (exeStatus != null)
                exeStatus.SetMessage("InitScore", "初始化");

            InitScore(waterSpans, tempSpans);//初始化分数字典

            if (exeStatus != null)
                exeStatus.DeleteMessage("InitScore");

            if ((CulculatePrecipitationWaterScore && PrecipitationWaterScore == null) ||
                (CulculateWaterfallLevelWaterScore && WaterfallLevelWaterScore == null) ||
                (CulculateSumPrecipitationWaterScore && SumPrecipitationWaterScore == null) || 
                (CulculateWaterfallAmountWaterScore && WaterfallAmountWaterScore == null) || 
                (CulculateMaxTempScore && MaxTempScore == null) ||
                (CulculateMinTempScore && MinTempScore == null) || 
                RecordCount == null)
            {
                if (exeStatus != null)
                    exeStatus.CurrentStep = exeStatus.total_step;
                return;
            }

            DateTime begin = beginDate;
            do
            {
                DateTime end = DateTime.Parse(string.Format("{0}-{1}-01", begin.Year, begin.Month)).AddMonths(1).AddDays(-1);

                if (end > endDate)
                    end = endDate;

                string node = string.Format("Month{0}{1}", begin.Year, begin.Month);
                string msg = string.Format("获取{0}年{1}月数据", begin.Year, begin.Month);
                if (exeStatus != null)
                    exeStatus.SetMessage(node, msg);

                CulculateScore(begin, end, realtype, waterSpans, tempSpans, sendpoints);

                if (exeStatus != null)
                    exeStatus.DeleteMessage(node);
      
                begin = end.AddDays(1);

                if (end == endDate) break;
            }
            while (begin.Year < endDate.Year || (begin.Year == endDate.Year && begin.Month <= endDate.Month));

        }

        /// <summary>
        /// 计算结果
        /// </summary>
        /// <param name="beginDate"></param>
        /// <param name="endDate"></param>
        /// <param name="realtype"></param>
        /// <param name="waterSpans"></param>
        /// <param name="tempSpans"></param>
        /// <param name="sendpoints"></param>
        private void CulculateScore(DateTime beginDate, DateTime endDate, ForeSemiType realtype, ForeSpanType[] waterSpans, ForeSpanType[] tempSpans, ForeSendpointType[] sendpoints)
        {
         
            //_beginDate = beginDate;
            //_endDate = endDate;
            //_realtype = realtype;
            //_waterSpans = waterSpans;
            //_tempSpans = tempSpans;
            //_sendpoints = sendpoints;

            //if (exeStatus != null)
            //    exeStatus.SetMessage("InitScore", "初始化");

            //InitScore(waterSpans, tempSpans);//初始化分数字典

            //if (exeStatus != null)
            //    exeStatus.DeleteMessage("InitScore");

            SendpointToClock parser = new SendpointToClock();
            ForeClockType[] clocks = parser.GetClockArrayWithSendPointArray(sendpoints);
            
            WaterScoreCalculate waterCalculate = null;
            DeviationResultCulculate deviationCulculate = null;
            if (CulculateWeatherScore)
                waterCalculate = new WaterScoreCalculate();
            if (CulculateDeviationResult)
                deviationCulculate = new DeviationResultCulculate();

            #region 计算天气与预报偏差
            if (waterSpans != null)
            {
                if (exeStatus != null)
                    exeStatus.SetMessage("waterSpans", "计算天气");

                foreach (ForeSpanType span in waterSpans)
                {
                    if (exeStatus != null)
                    {
                        exeStatus.SetMessage(span.ToString(), "时效:" + span.ToString());
                        //exeStatus.CurrentStep++;
                    }
                    TemCulculateWaterfallAmountWaterScore = CulculateWaterfallAmountWaterScore;
                    TemCulculateWaterfallLevelWaterScore = CulculateWaterfallLevelWaterScore;

                    ForeEntity[] semis;

                    if (CulculateWeatherScore && (CulculateWaterfallAmountWaterScore || CulculateWaterfallLevelWaterScore))
                    {

                        if (realtype == ForeSemiType.Auto && ForeSpanTypeTools.Is24HourSpan(span))
                        {
                            ForeSpanType firstSpan, lastSpan;
                            ForeSpanTypeTools.Get12Spans(span, out firstSpan, out lastSpan);
                            semis = DataProvider.InquerySemiWithDateRange(beginDate, endDate, clocks, firstSpan, sendpoints, ForeFactorType.wth, realtype, false);
                            if (exeStatus != null)
                                exeStatus.CurrentStep++;
                         
                            foreach (ForeEntity semi1 in semis)
                            {
                                if (semi1.Semi == "")
                                {
                                    EmptySemis.Add(semi1);
                                    continue;
                                }

                                if (CulculateWaterfallAmountSplitFD24ToFD12 && CulculateWaterfallLevelSplitFD24ToFD12)
                                    waterCalculate.CalculateWaterScoreBySemiString(null, WaterfallLevelWaterScore, null, WaterfallAmountWaterScore, RecordCount, semi1, span, CityCodes, Schedules);
                                else if (CulculateWaterfallAmountSplitFD24ToFD12)
                                    waterCalculate.CalculateWaterScoreBySemiString(null, null, null, WaterfallAmountWaterScore, RecordCount, semi1, span, CityCodes, Schedules);
                                else if (CulculateWaterfallLevelSplitFD24ToFD12)
                                    waterCalculate.CalculateWaterScoreBySemiString(null, WaterfallLevelWaterScore, null, null, RecordCount, semi1, span, CityCodes, Schedules);
                                
                            }

                            semis = DataProvider.InquerySemiWithDateRange(beginDate, endDate, clocks, lastSpan, sendpoints, ForeFactorType.wth, realtype, false);
                            if (exeStatus != null)
                                exeStatus.CurrentStep++;
                            foreach (ForeEntity semi2 in semis)
                            {
                                if (semi2.Semi == "")
                                {
                                    EmptySemis.Add(semi2);
                                    continue;
                                }

                                //注：以12小时为检验单元的24小时时效，后12小时的记录不参与统计样本数
                                if (CulculateWaterfallAmountSplitFD24ToFD12 && CulculateWaterfallLevelSplitFD24ToFD12)
                                    waterCalculate.CalculateWaterScoreBySemiString(null, WaterfallLevelWaterScore, null, WaterfallAmountWaterScore, null, semi2, span, CityCodes, Schedules);
                                else if (CulculateWaterfallAmountSplitFD24ToFD12)
                                    waterCalculate.CalculateWaterScoreBySemiString(null, null, null, WaterfallAmountWaterScore, null, semi2, span, CityCodes, Schedules);
                                else if (CulculateWaterfallLevelSplitFD24ToFD12)
                                    waterCalculate.CalculateWaterScoreBySemiString(null, WaterfallLevelWaterScore, null, null, null, semi2, span, CityCodes, Schedules);
                                
                            }

                            if (CulculateWaterfallAmountSplitFD24ToFD12)
                                TemCulculateWaterfallAmountWaterScore = false;
                            if (CulculateWaterfallLevelSplitFD24ToFD12)
                                TemCulculateWaterfallLevelWaterScore = false;
                        }


                    }

                    if ((CulculateWeatherScore && (CulculatePrecipitationWaterScore || TemCulculateWaterfallLevelWaterScore || CulculateSumPrecipitationWaterScore || TemCulculateWaterfallAmountWaterScore)) || CulculateDeviationResult)
                    {
                        semis = DataProvider.InquerySemiWithDateRange(beginDate, endDate, clocks, span, sendpoints, ForeFactorType.wth, realtype, false);
                        if (exeStatus != null)
                            exeStatus.CurrentStep++;
                        foreach (ForeEntity semi in semis)
                        {
                            if (semi.Semi == "")
                            {
                                EmptySemis.Add(semi);
                                continue;
                            }

                            if (CulculateWeatherScore)
                                waterCalculate.CalculateWaterScoreBySemiString(CulculatePrecipitationWaterScore == true ? PrecipitationWaterScore : null,
                                                                               TemCulculateWaterfallLevelWaterScore == true ? WaterfallLevelWaterScore : null,
                                                                               CulculateSumPrecipitationWaterScore == true ? SumPrecipitationWaterScore : null,
                                                                               TemCulculateWaterfallAmountWaterScore == true ? WaterfallAmountWaterScore : null,
                                                                               TemCulculateWaterfallAmountWaterScore == true ? RecordCount : null,
                                                                               semi, span, CityCodes, Schedules);



                            //计算偏差
                            if (CulculateDeviationResult)
                                deviationCulculate.CulculateDeviationResultBySemiString(this.connectionString, DeviationResults, semi.Semi, realtype);
                        }
                    }

                    if (exeStatus != null)
                    {
                        //exeStatus.CurrentStep++;
                        exeStatus.DeleteMessage(span.ToString());
                    }
                }

                if (exeStatus != null)
                    exeStatus.DeleteMessage("waterSpans");
            }
            #endregion

            #region 计算气温
            if (tempSpans != null)
            {
                if (exeStatus != null)
                    exeStatus.SetMessage("tempSpans", "计算气温");

                TempScoreCalculate tempCalculate = new TempScoreCalculate();

                foreach (ForeSpanType span in tempSpans)
                {
                    if (exeStatus != null)
                    {
                        exeStatus.SetMessage(span.ToString(), "时效:" + span.ToString());
                        //exeStatus.CurrentStep++;
                    }

                    ForeEntity[] semis = null;

                    if (CulculateMaxTempScore)
                    {
                        semis = DataProvider.InquerySemiWithDateRange(beginDate, endDate, clocks, span, sendpoints, ForeFactorType.maxt, realtype, false);
                        if (exeStatus != null)
                            exeStatus.CurrentStep++;
                        foreach (ForeEntity semi in semis)
                        {
                            if (semi.Semi == "")
                            {
                                EmptySemis.Add(semi);
                                continue;
                            }
                            tempCalculate.CulculateTemperatureScoreBySemiString(MaxTempScore, semi, span, CityCodes, Schedules);
                        }
                    }
                    if (CulculateMinTempScore)
                    {
                        semis = DataProvider.InquerySemiWithDateRange(beginDate, endDate, clocks, span, sendpoints, ForeFactorType.mint, realtype, false);
                        if (exeStatus != null)
                            exeStatus.CurrentStep++;
                        foreach (ForeEntity semi in semis)
                        {
                            if (semi.Semi == "")
                            {
                                EmptySemis.Add(semi);
                                continue;
                            }
                            tempCalculate.CulculateTemperatureScoreBySemiString(MinTempScore, semi, span, CityCodes, Schedules);
                        }
                    }

                    if (exeStatus != null)
                    {
                        //exeStatus.CurrentStep++;
                        exeStatus.DeleteMessage(span.ToString());
                    }

                }

                if (exeStatus != null)
                    exeStatus.DeleteMessage("tempSpans");
            }
            #endregion
        }

        /// <summary>
        /// 获取任务执行的总步数
        /// </summary>
        /// <param name="beginDate">开始时间</param>
        /// <param name="endDate">结束时间</param>
        /// <param name="realtype">实况类型</param>
        /// <param name="waterSpans">天气时效</param>
        /// <param name="tempSpans">温度时效</param>
        /// <returns></returns>
        public int GetExeStatusTotalSteps(DateTime beginDate, DateTime endDate, ForeSemiType realtype, ForeSpanType[] waterSpans, ForeSpanType[] tempSpans)
        {
            int waterSteps = 0;
            foreach (ForeSpanType span in waterSpans)
            {
                TemCulculateWaterfallAmountWaterScore = CulculateWaterfallAmountWaterScore;
                TemCulculateWaterfallLevelWaterScore = CulculateWaterfallLevelWaterScore;

                if (ForeSpanTypeTools.Is24HourSpan(span))
                {
                    if ((CulculateWaterfallAmountWaterScore && CulculateWaterfallAmountSplitFD24ToFD12) || (CulculateWaterfallLevelWaterScore && CulculateWaterfallLevelSplitFD24ToFD12))
                    {
                        waterSteps += 2;
                        if (CulculateWaterfallAmountSplitFD24ToFD12)
                            TemCulculateWaterfallAmountWaterScore = false;
                        if (CulculateWaterfallLevelSplitFD24ToFD12)
                            TemCulculateWaterfallLevelWaterScore = false;
                    }
                }

                if (CulculatePrecipitationWaterScore || TemCulculateWaterfallLevelWaterScore || CulculateSumPrecipitationWaterScore || TemCulculateWaterfallAmountWaterScore || CulculateDeviationResult)
                    waterSteps++;
            }

            int tempSteps = 0;
            if (CulculateMaxTempScore)
                tempSteps = tempSpans.Length;
            if(CulculateMinTempScore)
                tempSteps += tempSpans.Length;

            int months = 1;
            
            while (beginDate.Year !=endDate.Year || beginDate.Month != endDate.Month)
            {
                months++;
                beginDate = beginDate.AddMonths(1);
            }

            return (waterSteps + tempSteps) * months;
            //return (waterSpans.Length + tempSpans.Length) * months;
        }
        #endregion

        #region 计算综合分
        /// <summary>
        /// 计算预报员短期预报综合分
        /// </summary>
        /// <param name="key">城市编号或预报员编号</param>
        /// <returns></returns>
        public virtual float CalIndividualShortCompositeScore(string key)
        {
            if (RecordCount == null || (!RecordCount[key].ContainsKey(ForeSpanType.FD00_24) && !RecordCount[key].ContainsKey(ForeSpanType.FD24_48)))
                return 0;

            float pc_24 = WaterfallAmountWaterScore[key][ForeSpanType.FD00_24].CalPC();//计算24小时晴雨(pc)
            float normal_24 = WaterfallLevelWaterScore[key][WaterfallLevel.Normal][ForeSpanType.FD00_24].CalTS(); //计算24小时一般性降水
            float pc_48 = WaterfallAmountWaterScore[key][ForeSpanType.FD24_48].CalPC();//计算48小时晴雨(pc)
            float normal_48 = WaterfallLevelWaterScore[key][WaterfallLevel.Normal][ForeSpanType.FD24_48].CalTS(); //计算48小时一般性降水
            float maxt2_24 = MaxTempScore[key][ForeSpanType.FD00_24].Tt(2); //计算24小时最高温度2度误差
            float mint2_24 = MinTempScore[key][ForeSpanType.FD00_24].Tt(2);//计算24小时最低温度2度误差
            float maxt2_48 = MaxTempScore[key][ForeSpanType.FD24_48].Tt(2); //计算48小时最高温度2度误差
            float mint2_48 = MinTempScore[key][ForeSpanType.FD24_48].Tt(2);//计算24小时最低温度2度误差

            int count_24 = GetRecordCountBySpan(key, ForeSpanType.FD00_24);//取出24小时预报样本数
            int count_48 = GetRecordCountBySpan(key, ForeSpanType.FD24_48); //取出48小时预报样本数

            //if (RecordCount[key].ContainsKey(ForeSpanType.FD00_24))//取出24小时预报样本数
            //    count_24 = RecordCount[key][ForeSpanType.FD00_24];
            //if (RecordCount[key].ContainsKey(ForeSpanType.FD24_48)) //取出48小时预报样本数
            //    count_48 = RecordCount[key][ForeSpanType.FD24_48];

            //float a = count_24 * 1f / (count_24 + count_48);
            //float b = count_48 * 1f / (count_24 + count_48);

            return CalculateComposition(pc_24, normal_24, pc_48, normal_48, maxt2_24, mint2_24, maxt2_48, mint2_48, count_24, count_48);
        }

        /// <summary>
        /// 计算预报员中期预报综合分
        /// </summary>
        /// <param name="key">城市编号或预报员编号</param>
        /// <returns></returns>
        public float CalIndividualMiddleCompositeScore(string key)
        {

            float pc_96 = WaterfallAmountWaterScore[key][ForeSpanType.FD96_120].CalPC(); //计算24小时晴雨(pc)
            float normal_96 = WaterfallLevelWaterScore[key][WaterfallLevel.Normal][ForeSpanType.FD96_120].CalTS();//计算24小时一般性降水
            float pc_120 = WaterfallAmountWaterScore[key][ForeSpanType.FD120_144].CalPC();  //计算48小时晴雨(pc)
            float normal_120 = WaterfallLevelWaterScore[key][WaterfallLevel.Normal][ForeSpanType.FD96_120].CalTS(); //计算48小时一般性降水
            float maxt2_96 = MaxTempScore[key][ForeSpanType.FD96_120].Tt(2); //计算24小时最高温度2度误差
            float mint2_96 = MinTempScore[key][ForeSpanType.FD96_120].Tt(2);  //计算24小时最低温度2度误差
            float maxt2_120 = MaxTempScore[key][ForeSpanType.FD96_120].Tt(2); //计算48小时最高温度2度误差
            float mint2_120 = MinTempScore[key][ForeSpanType.FD96_120].Tt(2); //计算24小时最低温度2度误差

            int count_96 = GetRecordCountBySpan(key, ForeSpanType.FD96_120);//取出24小时预报样本数
            int count_120 = GetRecordCountBySpan(key, ForeSpanType.FD120_144); //取出48小时预报样本数

            //if (RecordCount[key].ContainsKey(ForeSpanType.FD96_120))//取出24小时预报样本数
            //    count_96 = GetRecordCount(key, ForeSpanType.FD96_120); //RecordCount[key][ForeSpanType.FD96_120];
            //if (RecordCount[key].ContainsKey(ForeSpanType.FD120_144)) //取出48小时预报样本数
            //    count_120 = RecordCount[key][ForeSpanType.FD120_144];

            //float a = count_96 * 1f / (count_96 + count_120);
            //float b = count_120 * 1f / (count_96 + count_120);

            return CalculateComposition(pc_96, normal_96, pc_120, normal_120, maxt2_96, mint2_96, maxt2_120, mint2_120, count_96, count_120);
        }

        /// <summary>
        /// 计算预报员综合分
        /// </summary>
        /// <param name="key">城市编号或预报员编号</param>
        /// <returns></returns>
        public float CalIndividualCompositeScore(string key)
        {
            if (IsShortCompositeScore)
                return CalIndividualShortCompositeScore(key);
            else
                return CalIndividualMiddleCompositeScore(key);
        }

        /// <summary>
        /// 计算集体综合分
        /// </summary>
        /// <param name="key">城市编号或预报员编号</param>
        /// <returns></returns>
        public float CalCollectCompositeScore(string key)
        {
            return 0.0f;
        }
        #endregion

        #region 获取得分字符串
        /// <summary>
        /// 获取得分字符串
        /// </summary>        
        /// <param name="standardReport">用来比较的标准数据，ss将与之进行比较</param>
        /// <param name="key">城市编号或预报员编号</param>
        public string ToResultString(FullInfoReport standardReport,string key)
        {
            return JsonConvert.SerializeObject(ToResult(standardReport, key));
        }
        #endregion

        #region 获取格式化后的得分
        /// <summary>
        /// 获取格式化后的得分
        /// </summary>        
        /// <param name="standardReport">用来比较的标准数据，ss将与之进行比较</param>
        /// <param name="key">城市编号或预报员编号</param>
        public Dictionary<string, object> ToResult(FullInfoReport standardReport, string key)
        {
            Dictionary<string, object> result = new Dictionary<string, object>();
            result.Add("wth", GetWaterScoreResult(standardReport, key));
            result.Add("temp", GetTempResult(standardReport,key));

            return result;
        }
        #endregion

        #region 格式化分级检验、累加降水、一般降水及暴雨以上、晴雨得分
        /// <summary>
        /// 计算并格式化分级检验、累加降水、一般降水及暴雨以上、晴雨得分
        /// </summary>
        /// <param name="standardReport">用来比较的标准数据，ss将与之进行比较</param>
        /// <param name="key">城市编号或预报员编号</param>
        /// <returns></returns>
        public Dictionary<ForeSpanType, Dictionary<string, Water>> GetWaterScoreResult(FullInfoReport standardReport,string key)
        {
            Dictionary<ForeSpanType, Dictionary<string, Water>> result = new Dictionary<ForeSpanType, Dictionary<string, Water>>();
            WaterScore memberWaterScore, standardWaterScore;
           
            foreach (ForeSpanType span in _waterSpans)
            {
                result.Add(span, new Dictionary<string, Water>());

                #region 计算分级检验
                string[] keys1 = { "", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "l8", "l9", "l10", "l11" };
                foreach (PrecipitationLevel level in Enum.GetValues(typeof(PrecipitationLevel)))
                {
                    if (PrecipitationWaterScore == null)
                    {
                        if ((int)level < 1 || (int)level >= keys1.Length)
                            continue;
                        result[span].Add(keys1[(int)level], new Water(0, 0, 0, 0));
                        continue;
                    }

                    if (!PrecipitationWaterScore[key].ContainsKey(level)) continue;

                    memberWaterScore = PrecipitationWaterScore[key][level][span];
                    standardWaterScore = standardReport.PrecipitationWaterScore[key][level][span];

                    result[span].Add(keys1[(int)level], new Water(memberWaterScore.TS, standardWaterScore.TS, memberWaterScore.FAR, memberWaterScore.PO));
                    
                }
                #endregion

                #region 计算累加降水
                string[] keys2 = { "", "g01", "g10", "g25", "g50" };
                foreach (SumPrecipitationLevel level in Enum.GetValues(typeof(SumPrecipitationLevel)))
                {
                    if (SumPrecipitationWaterScore == null)
                    {
                        if ((int)level < 1 || (int)level >= keys2.Length) 
                            continue;
                        result[span].Add(keys2[(int)level], new Water(0, 0, 0, 0));
                        continue;
                    }

                    if (!SumPrecipitationWaterScore[key].ContainsKey(level)) continue;

                    memberWaterScore = SumPrecipitationWaterScore[key][level][span];
                    standardWaterScore = standardReport.SumPrecipitationWaterScore[key][level][span];

                    result[span].Add(keys2[(int)level], new Water(memberWaterScore.TS, standardWaterScore.TS, memberWaterScore.FAR, memberWaterScore.PO));

                }
                #endregion

                #region  计算一般降水及暴雨以上
                string[] keys3 = { "", "", "", "", "", "", "", "", "", "", "n1", "n2" };
                foreach (WaterfallLevel level in Enum.GetValues(typeof(WaterfallLevel)))
                {
                    if (WaterfallLevelWaterScore == null)
                    {
                        if ((int)level < 10 || (int)level >= keys3.Length)
                            continue;
                        result[span].Add(keys3[(int)level], new Water(0, 0, 0, 0));
                        continue;
                    }

                    if (!WaterfallLevelWaterScore[key].ContainsKey(level)) continue;

                    memberWaterScore = WaterfallLevelWaterScore[key][level][span];
                    standardWaterScore = standardReport.WaterfallLevelWaterScore[key][level][span];

                    result[span].Add(keys3[(int)level], new Water(memberWaterScore.TS, standardWaterScore.TS, memberWaterScore.FAR, memberWaterScore.PO));

                }
                #endregion

                #region 计算晴雨
                if (WaterfallLevelWaterScore == null)
                    result[span].Add("pc", new Water(0, 0, 0, 0));
                else
                {
                    memberWaterScore = WaterfallAmountWaterScore[key][span];
                    standardWaterScore = standardReport.WaterfallAmountWaterScore[key][span];

                    result[span].Add("pc", new Water(memberWaterScore.PC, standardWaterScore.PC, memberWaterScore.FAR, memberWaterScore.PO));
                }
                #endregion

            }

            return result;
        }
        #endregion

        #region 格式化最高温及最低温得分
        /// <summary>
        /// 计算并格式化最高温及最低温得分
        /// </summary>
        /// <param name="key">城市编号或预报员编号</param>
        /// <returns></returns>
        public Dictionary<ForeSpanType, Dictionary<string, Temp>> GetTempResult(FullInfoReport standardReport,string key)
        {
            Dictionary<ForeSpanType, Dictionary<string, Temp>> result = new Dictionary<ForeSpanType, Dictionary<string, Temp>>();

            foreach (ForeSpanType span in _tempSpans)
            {
                result.Add(span, new Dictionary<string, Temp>());

                if (MaxTempScore == null)
                    result[span].Add("maxt", new Temp(0, 0, 0, 0, 0, 0));
                else
                {
                    float tame = MaxTempScore[key][span].Tame;
                    float trmse = MaxTempScore[key][span].Trmse;
                    float acc1 = MaxTempScore[key][span].Tt1;
                    float acc2 = MaxTempScore[key][span].Tt2;
                    float ss1 = GlobalFunction.CalculateTempSkill(MaxTempScore[key][span].Tt1, standardReport.MaxTempScore[key][span].Tt1);
                    float ss2 = GlobalFunction.CalculateTempSkill(MaxTempScore[key][span].Tt2, standardReport.MaxTempScore[key][span].Tt2);
                    result[span].Add("maxt", new Temp(tame, trmse, acc1, acc2, ss1, ss2));
                }

                if (MinTempScore == null)
                    result[span].Add("mint", new Temp(0, 0, 0, 0, 0, 0));
                else
                {
                    float tame = MinTempScore[key][span].Tame;
                    float trmse = MinTempScore[key][span].Trmse;
                    float acc1 = MinTempScore[key][span].Tt1;
                    float acc2 = MinTempScore[key][span].Tt2;
                    float ss1 = GlobalFunction.CalculateTempSkill(MinTempScore[key][span].Tt1, standardReport.MinTempScore[key][span].Tt1);
                    float ss2 = GlobalFunction.CalculateTempSkill(MinTempScore[key][span].Tt2, standardReport.MinTempScore[key][span].Tt2);
                    result[span].Add("mint", new Temp(tame, trmse, acc1, acc2, ss1, ss2));
                }
            }

            return result;
        }
        #endregion

        #region 计算并格式化偏差统计结果
        /// <summary>
        /// 计算并格式化偏差统计结果
        /// </summary>
        /// <returns></returns>
        public Deviation GetDeviationResult()
        {
            Deviation deviation = new Deviation();

            foreach (DeviationResult r in DeviationResults)
            {
                if (r.kind == DeviationKind.Ignore)
                    continue;
                else if (r.kind == DeviationKind.NoDeviation)
                    deviation.noDeviation++;
                else if (r.kind == DeviationKind.AllEmpty)
                    deviation.allEmpty++;
                else if (r.kind == DeviationKind.AllLack)
                    deviation.allLack++;
                else if (r.kind == DeviationKind.Reverse)
                    deviation.reverse++;

                else if (r.Direction == DeviationDirection.East)
                    deviation.East++;
                else if (r.Direction == DeviationDirection.EastNorth)
                    deviation.EastNorth++;
                else if (r.Direction == DeviationDirection.EastSouth)
                    deviation.EastSouth++;
                else if (r.Direction == DeviationDirection.North)
                    deviation.North++;
                else if (r.Direction == DeviationDirection.Sourh)
                    deviation.Sourh++;
                else if (r.Direction == DeviationDirection.SouthWest)
                    deviation.SouthWest++;
                else if (r.Direction == DeviationDirection.West)
                    deviation.West++;
                else if (r.Direction == DeviationDirection.WestNorth)
                    deviation.WestNorth++;
            }

            return deviation;
        }
        #endregion

        #region 获取样本数
        /// <summary>
        /// 获取预报员总的样本数
        /// </summary>
        /// <param name="key">预报员编号</param>
        /// <returns></returns>
        public int GetTotalRecordCount(string key)
        {
            int count=0;
            foreach (KeyValuePair<ForeSpanType, Dictionary<DateTime, int>> pair1 in RecordCount[key])
            {
                foreach (KeyValuePair<DateTime, int> pair2 in pair1.Value)
                    count += pair2.Value;
            }
            return count;
        }

        /// <summary>
        /// 获取预报员值班数
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public int GetSchedulesDays(string key)
        {
            List<DateTime> days = new List<DateTime>();
            foreach (KeyValuePair<ForeSpanType, Dictionary<DateTime, int>> pair1 in RecordCount[key])
            {
                foreach (KeyValuePair<DateTime, int> pair2 in pair1.Value)
                {
                    if (!days.Contains(pair2.Key))
                        days.Add(pair2.Key);
                }
            }
            return days.Count;
        }

        /// <summary>
        /// 获取预报员指定预报时效的样本数
        /// </summary>
        /// <param name="key"></param>
        /// <param name="span"></param>
        /// <returns></returns>
        public int GetRecordCountBySpan(string key, ForeSpanType span)
        {
            int count = 0;
            if (RecordCount[key].ContainsKey(span))
            {
                foreach (KeyValuePair<DateTime, int> pair in RecordCount[key][span])
                    count += pair.Value;
            }
            return count;
        }

        /// <summary>
        /// 获取预报员每个月的样本数
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Dictionary<string ,int> GetEveryMonthRecordCount(string key)
        {
            Dictionary<string, int> count = new Dictionary<string, int>();
            foreach (KeyValuePair<ForeSpanType, Dictionary<DateTime, int>> pair1 in RecordCount[key])
            {
                foreach (KeyValuePair<DateTime, int> pair2 in pair1.Value)
                {
                    string month = pair2.Key.ToString("yyyyMM");
                    if (!count.ContainsKey(month))
                        count.Add(month, pair2.Value);
                    else
                        count[month] += pair2.Value;
                }
            }
            return count;
        }

        #endregion

    }

    #region 用于JSON序列化的类
    /// <summary>
    /// 用于JSON序列化的预报偏差数值类
    /// </summary>
    public class Deviation
    {
        public int noDeviation = 0;
        public int allEmpty = 0;
        public int allLack = 0;
        public int reverse = 0;
        public int East = 0;
        public int Sourh = 0;
        public int West = 0;
        public int North = 0;
        public int EastSouth = 0;
        public int SouthWest = 0;
        public int WestNorth = 0;
        public int EastNorth = 0;
    }

    /// <summary>
    /// 用于JSON序列化的降水数值类
    /// </summary>
    public class Water
    {
        public float ts;
        public float ss;
        /// <summary>
        /// 空报率
        /// </summary>
        public float er;
        /// <summary>
        /// 漏报率
        /// </summary>
        public float lr;

        public Water()
        { }
        

        /// <summary>
        /// 
        /// </summary>
        /// <param name="TS"></param>
        /// <param name="StandardTS"></param>
        public Water(float TS, float StandardTS,float ER, float LR)
        {
            ts = float.Parse(string.Format("{0:N2}", TS));
            ss = float.Parse(string.Format("{0:N2}", GlobalFunction.CalculateWaterSkill(TS, StandardTS)));
            er = float.Parse(string.Format("{0:N2}", ER));
            lr = float.Parse(string.Format("{0:N2}", LR));
            
           
        }
    }

    /// <summary>
    /// 用于JSON序列化的气温数值类
    /// </summary>
    public class Temp
    {
        /// <summary>
        /// 平均绝对误差
        /// </summary>
        public float mae;
        /// <summary>
        /// 均方根误差
        /// </summary>
        public float rmse;
        /// <summary>
        /// 小于1℃预报准确率
        /// </summary>
        public float acc1;
        /// <summary>
        /// 小于2℃预报准确率
        /// </summary>
        public float acc2;
        /// <summary>
        /// 小于1℃预报技巧值
        /// </summary>
        public float ss1;
        /// <summary>
        /// 小于2℃预报技巧值
        /// </summary>
        public float ss2;

        public Temp()
        { }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Mae">平均绝对误差</param>
        /// <param name="Rmse">均方根误差</param>
        /// <param name="Acc1">小于1℃预报准确率</param>
        /// <param name="Acc2">小于2℃预报准确率</param>
        public Temp(float Mae, float Rmse, float Acc1, float Acc2,float Ss1,float Ss2)
        {
            mae = float.Parse(string.Format("{0:N2}", Mae));
            rmse = float.Parse(string.Format("{0:N2}", Rmse)); 
            acc1 = float.Parse(string.Format("{0:N2}", Acc1));
            acc2 = float.Parse(string.Format("{0:N2}", Acc2));
            ss1 = float.Parse(string.Format("{0:N2}", Ss1));
            ss2 = float.Parse(string.Format("{0:N2}", Ss2));
        }

    }
#endregion

}

